use sha2::{Digest, Sha256};
use tokio::fs;

use crate::{app_error::AppError, app_writer::AppResult, config::CFG};

pub fn hash_file(data: &[u8]) -> String {
    let mut hasher = Sha256::new();
    hasher.update(data);
    let result = hasher.finalize();
    format!("{:x}", result)
}

pub async fn file_write(filename: &str, data: &[u8]) -> AppResult<()> {
    let path = get_file_path(filename);
    fs::write(path, data).await?;
    Ok(())
}

pub async fn file_remove(filename: &str) -> AppResult<()> {
    let path = get_file_path(filename);
    fs::remove_file(path).await?;
    Ok(())
}

pub fn get_file_path(filename: &str) -> String {
    let dict = CFG.storage.directory.as_str();
    let path = format!("{dict}/{filename}");
    path
}

pub fn extract_string_from_txt(data: &[u8]) -> AppResult<String> {
    let res = String::from_utf8_lossy(data).to_string();
    Ok(res)
}

pub fn extract_string_from_pdf(data: &[u8]) -> AppResult<String> {
    let res = pdf_extract::extract_text_from_mem(&data)
    .map_err(|_| anyhow::anyhow!("pdf extract error"))?;
    Ok(res)
}

pub fn extract_string(data: &[u8], file_type: &str) -> AppResult<String> {
    let file_type = file_type.to_lowercase();
    let file_type = file_type.trim();
    match file_type {
        "txt" => extract_string_from_txt(data),
        "pdf" => extract_string_from_pdf(data),
        _ => {
            let err = anyhow::anyhow!("unknown file type");
            Err(AppError::from(err))
        },
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_hash_file() {
        let data = b"hello world";
        let hash = hash_file(data);
        assert_eq!(
            hash,
            "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
        );
    }

    #[test]
    fn test_extract_as_pdf() {
        let path = "/home/yang/文档/2312.16171v2.pdf"; // 替换为你的PDF文件路径
        let data = std::fs::read(path).unwrap();
        let text = extract_string_from_pdf(&data).unwrap();
        println!("{}", text.len());
        println!("{}", text);
    }
}
